package downloader

import (
	"fmt"
	"net/url"
	"path"
	"time"

	"github.com/jlaffaye/ftp"
)

// FTPDownloader implements the Downloader interface for FTP/FTPS
type FTPDownloader struct {
	BaseDownloader
	client *ftp.ServerConn
}

// NewFTPDownloader creates a new FTP downloader
func NewFTPDownloader(config *Config) *FTPDownloader {
	return &FTPDownloader{
		BaseDownloader: BaseDownloader{
			config:   config,
			stopChan: make(chan struct{}),
		},
	}
}

// Download starts the FTP download
func (d *FTPDownloader) Download(urlStr string) error {
	u, err := url.Parse(urlStr)
	if err != nil {
		return fmt.Errorf("invalid URL: %w", err)
	}

	// Connect to FTP server
	d.client, err = ftp.Dial(u.Host, ftp.DialWithTimeout(5*time.Second))
	if err != nil {
		return fmt.Errorf("failed to connect to FTP server: %w", err)
	}
	defer d.client.Quit()

	// Login
	if u.User != nil {
		password, _ := u.User.Password()
		if err := d.client.Login(u.User.Username(), password); err != nil {
			return fmt.Errorf("failed to login: %w", err)
		}
	} else {
		// Anonymous login
		if err := d.client.Login("anonymous", "anonymous"); err != nil {
			return fmt.Errorf("failed to login anonymously: %w", err)
		}
	}

	// Download file
	resp, err := d.client.Retr(u.Path)
	if err != nil {
		return fmt.Errorf("failed to retrieve file: %w", err)
	}
	defer resp.Close()

	filename := path.Base(u.Path)
	d.initProgress(-1, filename) // FTP might not provide file size

	// Create output file
	out, err := d.createOutputFile(filename)
	if err != nil {
		return err
	}
	defer out.Close()
	// 创建临时目录
	tempErr := d.createTempFile()
	if tempErr != nil {
		return tempErr
	}
	defer out.Close()

	return d.copyWithProgress(out, resp)
}

func (d *FTPDownloader) Stop() error {
	if d.client != nil {
		d.client.Quit()
	}
	close(d.stopChan)
	return nil
}

func (d *FTPDownloader) Progress() float64 {
	d.mu.Lock()
	defer d.mu.Unlock()
	if d.totalSize == 0 {
		return 0
	}
	return float64(d.downloaded) / float64(d.totalSize) * 100
}

func (d *FTPDownloader) Speed() int64 {
	return 0 // TODO: Implement speed calculation
}
